﻿using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json.Linq;
using SpriteAtlasRuntime;

namespace AnimationPackerEngine.Animation.CommandWriters
{
    internal class If : ICommandWriter
    {
        private CompareTypes mCompareType;
        private CompareTargets mCompareTarget;
        private float mCompareValue;

        private List<ICommandWriter> mThenBlock;
        public List<ICommandWriter> ThenBlock
        {
            get { return mThenBlock; }
        }

        private List<ICommandWriter> mElseBlock;
        public List<ICommandWriter> ElseBlock
        {
            get { return mElseBlock; }
        }

        internal If(JArray condition)
        {
            mThenBlock = new List<ICommandWriter>();
            mElseBlock = new List<ICommandWriter>();

            if (!Enum.TryParse<CompareTargets>((string)condition[0], true, out mCompareTarget))
            {
                throw new InvalidDataException(string.Format("Could not parse a CompareTargets value from {0}.", condition[0]));
            }

            switch ((string)condition[1])
            {
                case "<":
                    mCompareType = CompareTypes.LessThan;
                    break;

                case "<=":
                    mCompareType = CompareTypes.LessThanOrEqual;
                    break;

                case "==":
                    mCompareType = CompareTypes.Equal;
                    break;

                case "!=":
                    mCompareType = CompareTypes.NotEqual;
                    break;

                case ">=":
                    mCompareType = CompareTypes.GreaterThanOrEqual;
                    break;
                    
                case ">":
                    mCompareType = CompareTypes.GreaterThan;
                    break;

                default:
                    throw new InvalidDataException(string.Format("Could not parse a CompareTypes value from {0}. Expected one of [<,<=,==,!=,>=,>].", condition[1]));
            }

            mCompareValue = (float)condition[2];
        }

        public void Write(BinaryWriter binaryWriter, IWriterContext context)
        {
            binaryWriter.Write((int)ScriptCommands.If);
            binaryWriter.Write((int)mCompareTarget);
            binaryWriter.Write((int)mCompareType);
            binaryWriter.Write((float)mCompareValue);

            {
                byte[] thenBlockData;
                using (MemoryStream thenBlockStream = new MemoryStream())
                {
                    using (BinaryWriter thenBlockWriter = new BinaryWriter(thenBlockStream))
                    {
                        foreach (ICommandWriter writer in mThenBlock)
                        {
                            writer.Write(thenBlockWriter, context);
                        }
                    }

                    thenBlockData = thenBlockStream.ToArray();
                }

                binaryWriter.Write((int)ScriptCommands.End - 1);
                binaryWriter.Write(thenBlockData.Length);

                if (thenBlockData.Length > 0)
                {
                    binaryWriter.Write(thenBlockData);
                }
            }

            {
                byte[] elseBlockData;
                using (MemoryStream elseBlockStream = new MemoryStream())
                {
                    using (BinaryWriter elseBlockWriter = new BinaryWriter(elseBlockStream))
                    {
                        foreach (ICommandWriter writer in mElseBlock)
                        {
                            writer.Write(elseBlockWriter, context);
                        }
                    }

                    elseBlockData = elseBlockStream.ToArray();
                }

                binaryWriter.Write((int)ScriptCommands.End - 1);
                binaryWriter.Write(elseBlockData.Length);

                if (elseBlockData.Length > 0)
                {
                    binaryWriter.Write(elseBlockData);
                }
            }
        }
    }
}
